#ifndef __IM_SERVER_H__
#define __IM_SERVER_H__

#include <im_object.h>
#include <im_io_channel.h>
#include <im_main_loop.h>

/**
 * @defgroup IMServer
 * @ingroup PrivateIMBusIME
 * @{
 */

/** @struct IMServer
 *  @brief Interface class of a IM-BUS server.
 *
 *  The purpose of IMServer is to handle communication between IM-BUS clients
 *  and server.
 */

IM_BEGIN_DECLS

#define IM_SERVER(p)             (IM_TYPE_INSTANCE_CHECK_CAST((p),IM_TYPE_SERVER,IMServer))
#define IM_CONST_SERVER(p)       (IM_TYPE_INSTANCE_CHECK_CAST_CONST((p),IM_TYPE_SERVER,IMServer))
#define IM_SERVER_CLASS(c)       (IM_TYPE_CLASS_CHECK_CAST((c),IM_TYPE_SERVER,IMServerClass))
#define IM_IS_SERVER(p)          (IM_TYPE_INSTANCE_CHECK_TYPE((p),IM_TYPE_SERVER))
#define IM_IS_SERVER_CLASS(c)    (IM_TYPE_CLASS_CHECK_TYPE((c),IM_TYPE_SERVER))
#define IM_SERVER_GET_CLASS(p)   (IM_TYPE_INSTANCE_GET_CLASS_CAST((p),IM_TYPE_SERVER,IMServerClass))

typedef struct _IMServer                    IMServer;
typedef struct _IMServerClass               IMServerClass;

/**
 * @brief Callback function to handle new connections.
 *
 * This function will be called when a new connection is available.
 */
typedef void    (*IMNewConnectionHandler)   (IMServer       *server,
                                             IMIOChannel    *io_channel,
                                             IMPointer       data);

struct _IMServer
{
    IMInitiallyOwned parent_object;
};

struct _IMServerClass
{
    IMInitiallyOwnedClass parent_class;
    IMBool      (*listen)                   (IMServer               *server,
                                             const IMChar           *address,
                                             IMIOError              *error);
    IMBool      (*is_connected)             (IMServer               *server);
    void        (*disconnect)               (IMServer               *server);
    void        (*set_main_loop)            (IMServer               *server,
                                             IMMainLoop             *loop);
    IMMainLoop* (*get_main_loop)            (IMServer               *server);
    void    (*set_new_connection_handler)   (IMServer               *server,
                                             IMNewConnectionHandler  handler,
                                             IMPointer               data,
                                             IMDestroyFunc           data_destroy_func);
};

/**
 * @brief Create a new IMServer object for a specified IMServer type.
 *
 * The newly created IMServer object is owned by the creator
 * (not floating). So creator should unref it explicitly when it's not
 * used anymore.
 */
IMServer*   im_server_new               (IMType          type);

/**
 * @brief Create a new IMServer object and listen to a specific address.
 *
 * The newly created IMServer object is owned by the creator
 * (not floating). So creator should unref it explicitly when it's not
 * used anymore.
 */
IMServer*   im_server_new_listen        (const IMChar   *address,
                                         IMIOError      *error);

/**
 * @brief Let a IMServer object listen to a specified address.
 */
IMBool      im_server_listen            (IMServer       *server,
                                         const IMChar   *address,
                                         IMIOError      *error);

/**
 * @brief Check if a IMServer object is listening for new connections.
 */
IMBool      im_server_is_connected      (IMServer       *server);

/**
 * @brief Stop listening for new connections and release the server address.
 */
void        im_server_disconnect        (IMServer       *server);

/**
 * @brief Attach an IMServer object to a specified IMMainLoop object.
 *
 * If the server is already attached to a main loop object, then it'll be
 * detached first.
 */
void        im_server_set_main_loop     (IMServer       *server,
                                         IMMainLoop     *loop);

/**
 * @brief Get the IMMainLoop object which is currently used by a specified
 *        IMServer object.
 */
IMMainLoop* im_server_get_main_loop     (IMServer       *server);

/**
 * @brief Set a new connection handler to a IMServer object.
 *
 * The handler will be called when a new connection is available.
 */
void        im_server_set_new_connection_handler(IMServer              *server,
                                                 IMNewConnectionHandler handler,
                                                 IMPointer              data,
                                                 IMDestroyFunc          data_destroy_func);
IM_END_DECLS
/** @} */

#endif
/*
vi:ts=4:nowrap:ai:expandtab
*/
